﻿using AutoMapper;
using IOA.MES.Common;
using IOA.MES.DataAccess.Entity;
using IOA.MES.DataAccess.Enum;
using IOA.MES.DataAccess.VModel;
using IOA.MES.Log.Business;
using IOA.MES.Log.DataAccess.VModel;
using IOA.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOA.MES.Business
{
    /// <summary>
    /// OBA管理（错误代码：139001）
    /// </summary>
    public class ObaMgr
    {
        private MESContext mesDb = new MESContext("MES");

        /// <summary>
        /// 创建OBA
        /// </summary>
        /// <param name="model">OBA对象</param>
        public void CreateOba(VObaInspect model)
        {
            if (!model.Packs.Any())
            {
                throw new MultiLanBizException(139001);//请至少检测一个包装
            }
            else if (!model.Sites.Any())
            {
                throw new MultiLanBizException(139002);//请至少检测一个站点
            }
            var packNos = model.Packs.Select(_ => _.PackNo.ToUpper()).Distinct().ToList();
            var packs = mesDb.Packs.AsNoTracking().Where(_ => packNos.Contains(_.PackNo) && _.PackStatus == PackStatus.Normal && _.Valid).ToList();
            var orderNos = packs.Select(_ => _.OrderNo.ToUpper()).Distinct().ToList();
            var invalidPackNos = packNos.Where(_ => !packs.Select(p => p.PackNo).Contains(_)).ToList();
            if (invalidPackNos.Any())
            {
                throw new MultiLanBizException(139003, string.Join(", ", string.Join(", ", invalidPackNos)));//下列包装不存在或已被解包
            }
            else if (orderNos.Count > 1)
            {
                throw new MultiLanBizException(139006, string.Join(", ", string.Join(", ", orderNos)));//本次检测的包装不在同一个订单下，现在订单号如下
            }

            var testingPackNos = (from pack in mesDb.ObaPacks
                                  join oba in mesDb.ObaInspects on pack.ObaNo equals oba.ObaNo
                                  where oba.Status != ObaStatus.Finish && oba.Valid && pack.Valid && packNos.Contains(pack.PackNo)
                                  select pack.PackNo).Distinct().ToList();
            if (testingPackNos.Any())
            {
                throw new MultiLanBizException(139004, string.Join(", ", testingPackNos));//下列包装存在未完成的OBA检测
            }

            model.CreateTime = DateTime.Now;
            model.Status = ObaStatus.Testing;
            model.InnerOrderNo = packs.FirstOrDefault().InnerOrderNo;
            model.OrderNo = packs.FirstOrDefault().OrderNo;
            var entity = Mapper.Map<ObaInspect>(model);
            mesDb.ObaInspects.Add(entity);
            mesDb.SaveChanges();
            entity.ObaNo = DateTime.Now.ToString("yyMMddHHmmss") + (entity.PkId % 100).ToString("00");

            var obaPacks = packs.Select(_ => new ObaPack
            {
                ObaNo = entity.ObaNo,
                PackBatchNo = _.PackBatchNo,
                PackNo = _.PackNo,
                CabinetNo = _.CabinetNo,
                CreateBy = entity.CreateBy,
                CreateTime = DateTime.Now
            }).ToList();
            mesDb.ObaPacks.AddRange(obaPacks);

            var obaSites = model.Sites.Select(_ => new ObaSite
            {
                ObaNo = entity.ObaNo,
                SiteType = _.SiteType,
                CreateBy = entity.CreateBy,
                CreateTime = DateTime.Now
            }).ToList();
            mesDb.ObaSites.AddRange(obaSites);

            var components = mesDb.Components.AsNoTracking().Where(_ => packNos.Contains(_.PackNo) && _.Valid).ToList();
            components.ForEach(_ =>
            {
                mesDb.Components.Attach(_);
                _.ModifyBy = entity.CreateBy;
                _.ModifyTime = DateTime.Now;
                _.Testing = true;
            });
            mesDb.SaveChanges();

            new TaskFactory().StartNew(() =>
            {
                var user = new UserMgr().QueryUsers(new List<int> { model.CreateBy }).FirstOrDefault();
                var logs = components.Select(_ => new VOprLog
                {
                    SubjectType = "组件",
                    SubjectNo = _.BarCode,
                    LogName = "创建OBA",
                    LogStatus = "正常",
                    OpeatorId = model.CreateBy,
                    OpeatorName = user?.TrueName,
                    LogContent = $"组件被创建OBA，本次共创建OBA组件{obaPacks.Count}包，合{components.Count}块",
                    LogTime = DateTime.Now,
                    CreateBy = model.CreateBy
                }).ToList();
                new OprLogMgr().AddLogs(logs);
            });
        }

        /// <summary>
        /// 完成OBA
        /// </summary>
        /// <param name="model">OBA对象</param>
        public void FinishOba(VObaInspect model)
        {
            var obaEntity = mesDb.ObaInspects.AsNoTracking().FirstOrDefault(_ => _.ObaNo == model.ObaNo && _.Valid);
            if (obaEntity == null)
            {
                throw new MultiLanBizException(139005);//当前OBA检测不存在
            }
            var packNos = mesDb.ObaPacks.AsNoTracking().Where(_ => _.ObaNo == model.ObaNo && _.Valid).Select(_ => _.PackNo).ToList();
            var components = mesDb.Components.AsNoTracking().Where(_ => packNos.Contains(_.PackNo) && _.Valid).ToList();

            components.ForEach(_ =>
            {
                mesDb.Components.Attach(_);
                _.Testing = false;
                _.ModifyBy = model.ModifyBy;
                _.ModifyTime = DateTime.Now;
            });

            mesDb.ObaInspects.Attach(obaEntity);
            obaEntity.ModifyBy = model.ModifyBy;
            obaEntity.ModifyTime = DateTime.Now;
            obaEntity.FinishTime = DateTime.Now;
            obaEntity.Status = ObaStatus.Finish;
            mesDb.SaveChanges();

            new TaskFactory().StartNew(() =>
            {
                var user = new UserMgr().QueryUsers(new List<int> { model.CreateBy }).FirstOrDefault();
                var logs = components.Select(_ => new VOprLog
                {
                    SubjectType = "组件",
                    SubjectNo = _.BarCode,
                    LogName = "OBA完成",
                    LogStatus = "正常",
                    OpeatorId = model.CreateBy,
                    OpeatorName = user?.TrueName,
                    LogContent = $"OBA检测完成，本次共完成OBA组件{packNos.Count}包，合{components.Count}块",
                    LogTime = DateTime.Now,
                    CreateBy = model.CreateBy
                }).ToList();
                new OprLogMgr().AddLogs(logs);
            });
        }

        /// <summary>
        /// 查询OBA列表
        /// </summary>
        /// <param name="page">页面索引</param>
        /// <param name="limit">页面容量</param>
        /// <param name="total">总数量</param>
        /// <param name="orderNo">订单号</param>
        /// <param name="obaNo">Oba单号</param>
        /// <param name="finished">是否已完成</param>
        /// <param name="startTime">开始创建时间</param>
        /// <param name="endTime">截止创建时间</param>
        /// <returns>OBA列表</returns>
        public List<VObaInspectInfo> QueryObas(int page, int limit, out int total, string orderNo, string obaNo, ObaStatus? status, DateTime? startTime, DateTime? endTime)
        {
            var query = mesDb.ObaInspects.AsNoTracking().Where(_ => _.Valid);
            if (!string.IsNullOrWhiteSpace(orderNo))
            {
                query = query.Where(_ => _.OrderNo.Contains(orderNo));
            }
            if (!string.IsNullOrWhiteSpace(obaNo))
            {
                query = query.Where(_ => _.ObaNo.Contains(obaNo));
            }
            if (status.HasValue)
            {
                query = query.Where(_ => _.Status == status.Value);
            }
            if (startTime.HasValue)
            {
                query = query.Where(_ => _.CreateTime >= startTime.Value);
            }
            if (endTime.HasValue)
            {
                query = query.Where(_ => _.CreateTime < endTime.Value);
            }

            total = query.Count();

            query = query.OrderByDescending(_ => _.PkId);
            var entities = limit <= 0 ? query.ToList() : query.Skip((page - 1) * limit).Take(limit).ToList();
            var models = Mapper.Map<List<VObaInspectInfo>>(entities);

            var userIds = models.Select(_ => _.CreateBy).Distinct().ToList();
            var users = new UserMgr().QueryUsers(userIds);

            var orderNos = models.Select(_ => _.InnerOrderNo).Distinct().ToList();
            var orders = mesDb.Orders.AsNoTracking().Where(_ => orderNos.Contains(_.InnerOrderNo) && _.Valid).ToList();

            var obaNos = models.Select(_ => _.ObaNo).ToList();
            var sites = mesDb.ObaSites.AsNoTracking().Where(_ => obaNos.Contains(_.ObaNo) && _.Valid).ToList();
            var packs = mesDb.ObaPacks.AsNoTracking().Where(_ => obaNos.Contains(_.ObaNo) && _.Valid).ToList();
            models.ForEach(model =>
            {
                model.CustomerCode = orders.FirstOrDefault(o => StringUtils.Equals(o.InnerOrderNo, model.InnerOrderNo))?.CustomerCode;
                model.CustomerName = orders.FirstOrDefault(o => StringUtils.Equals(o.InnerOrderNo, model.InnerOrderNo))?.CustomerName;
                model.CNCreateBy = users.FirstOrDefault(_ => _.PkId == model.CreateBy)?.TrueName;
                model.Sites = Mapper.Map<List<VObaSite>>(sites.Where(_ => StringUtils.Equals(_.ObaNo, model.ObaNo)).ToList());
                model.Packs = Mapper.Map<List<VObaPack>>(packs.Where(_ => StringUtils.Equals(_.ObaNo, model.ObaNo)).ToList());
            });

            return models;
        }

        /// <summary>
        /// 查询OBA列表
        /// </summary>
        /// <param name="obaNo">OBA单号</param>
        /// <returns>OBA对象</returns>
        public VObaInspect GetOba(string obaNo)
        {
            var entity = mesDb.ObaInspects.AsNoTracking().FirstOrDefault(_ => _.ObaNo == obaNo && _.Valid);
            if (entity == null)
            {
                return null;
            }
            var model = Mapper.Map<VObaInspect>(entity);

            var obaPacks = mesDb.ObaPacks.AsNoTracking().Where(_ => _.Valid && _.ObaNo == entity.ObaNo).ToList();
            var obaSites = mesDb.ObaSites.AsNoTracking().Where(_ => _.Valid && _.ObaNo == entity.ObaNo).ToList();

            model.Packs.AddRange(Mapper.Map<List<VObaPack>>(obaPacks));
            model.Sites.AddRange(Mapper.Map<List<VObaSite>>(obaSites));

            var users = new UserMgr().QueryUsers(new List<int> { model.CreateBy });
            model.CNCreateBy = users.FirstOrDefault(_ => _.PkId == model.CreateBy)?.TrueName;

            return model;
        }

        /// <summary>
        /// 查询OBA包装清单
        /// </summary>
        /// <param name="obaNo">OBA单号</param>
        /// <returns>包装清单</returns>
        public List<VPack> QueryObaPacks(string obaNo)
        {
            var packNos = mesDb.ObaPacks.AsNoTracking().Where(_ => _.ObaNo == obaNo && _.Valid).Select(_ => _.PackNo).ToList();
            var packs = !packNos.Any() ? new List<Pack>() : mesDb.Packs.AsNoTracking().Where(_ => packNos.Contains(_.PackNo) && _.Valid).ToList();
            return Mapper.Map<List<VPack>>(packs.OrderBy(_ => _.OrderNo).ThenBy(_ => _.WorkOrderNo).ToList());
        }
    }
}
